/*
 * Proto Streamer
 * Copyright (C) 2009 John Pritchard.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 */
package p.s.m;

import com.google.protobuf.Message;

/**
 * A service is a producer's target and a consumer's source for
 * asynchronous stream messages.  A service may be a queue or a store,
 * depending on the usage of the application architecture.
 * 
 * Services may be subclassed by the application to implement
 * application protocols.
 * 
 * Services are managed as through the {@link p.s.q.Manager Queue
 * Manager} or {@link p.s.t.Map Map} for {@link p.s.t.Slot}.  A queue is
 * a session that may expire, and a map is not.
 * 
 * Some service classes may have the property of a session that
 * permits them to (automatically) expire, while others may not.
 * 
 * @see Consumer
 * @see Producer
 * @author jdp
 */
public interface Service 
    extends alto.sys.Lock.Advanced,
            p.s.Millis
{
    /**
     * @return Application identifier.
     */
    public Object getId();
    /**
     * @return Service identifier, typically system identity hash
     * code.
     */
    public int getServiceIdentity();
    /**
     * The state of the service is relative to the service version.
     * When the service clears, its version is incremented.
     */
    public long getServiceVersion();
    /**
     * A {@link Consumer} polls on this method for updates.  This
     * method will return null for no update within the waitfor
     * window, rather than wait indefinitely (block) for an update.
     * 
     * Not blocking gives the consumer the opportunity to poll with
     * its own frequency, and to generate heartbeat or stream warming
     * messages periodically.
     * 
     * @param waitfor Required positive number of milliseconds.  Wait
     * momentarily after an update has not been found, in order to
     * check once again before returning null.
     * 
     * This 'waitfor' is equivalent to an external approach.  It is
     * not guaranteed to avoid the race between the single argument
     * consumer update and the two argument producer update.
     * Therefore, recommended values for 'waitfor' are short: greater
     * than zero and less than five hundred (half second).  On this
     * frequency a consumer should periodically (for example every two
     * seconds) send a heartbeat message.
     */
    public Message update(Consumer c, long waitfor);
    /**
     * Update the service.  Append to a queue or replace in a store.
     */
    public void update(Producer p, Message m);
    /**
     * Clear the service releasing all message references, increment
     * version.  Causes all consumer pointers to reset.
     */
    public void clear(Producer p);
    /**
     * @return A service manager can drop it.
     */
    public boolean hasExpired();

    public boolean enterConsumer(Consumer c);

    public boolean exitConsumer(Consumer c);

    public boolean enterProducer(Producer p);

    public boolean exitProducer(Producer p);
    /**
     * Called after constructor.  A runtime exception here is printed
     * but otherwise has no effect on the service instantiation and
     * registration process.
     */
    public void init();
    /**
     * Called in release.  A runtime exception here is printed but
     * otherwise has no effect on the service deregistration process.
     */
    public void destroy();
}
